/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ChatController;
import ChatGUI.ChatGUI;
import ChatNI.ChatNI;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Observable;

/**
 *
 * @author Marion et Nicolas
 

/**La classe Model (Observable) est observée par la classe ChatGUI (Observer) : à chaque changement d'état du Model, 
le ChatGUI doit en être informé**/

public class Model extends Observable{
    
      /** La cle de notre HashMap est le login de l'utilisateur**/
    private static HashMap listUsers;    
     /** Une HashMap inverse pour pouvoir recuperer un login**/
    private static HashMap listUsersInverse;  
    private TypeOfNotify type;

     /**
     * Constructeur du Model
     */
    
   public Model(){
       Model.listUsers = new HashMap <String,InetAddress> ();
       Model.listUsersInverse = new HashMap <InetAddress,String> ();
       this.type = new TypeOfNotify();
   }

 
    /**
    *   Méthode permettant d'obtenir une addresse IP à partir d'un login
    * Cette méthode est utilisée par le Chatcontroller
    * @param login
    * @return 
    */
   public Object getAddrFromLogin(String login){
       return listUsers.get(login);
   }
   
    /**
    * Méthode permettant d'obtenir un login à partir d'une addresse IP
    * @param addr
    * @return 
    */
   
   public Object getLoginFromAddr(InetAddress addr){
       return listUsersInverse.get(addr);
   }

   
     /**
    * Méthode permettant d'afficher la fenetre de connection
    * Cette méthode notifie le ChatGUI de la connexion
    */
   
   protected void connected(){
       type.setNull();
       type.setConnected("YES");
       this.setChanged();
       ChatGUI.display=true;
       notifyObservers(type);
       System.out.println("Dans la méthode connected du Model");
       type.setNull();
   }
   
    /**
    * Méthode permettant de retourner à la fenêtre de déconnexion
    */
   
   protected void disconnected(){
       type.setNull();
       type.setDisconnected("YES");
       this.setChanged();
       notifyObservers(type);
       System.out.println("Dans la méthode disconnected du Model");
       type.setNull();
       listUsers.clear();               
   }
   
    /**
    * Méthode correspondant à la connexion d'un utilisateur au chat
    * Lors de la connexion d'un nouvel utilisateur, le Model change d'état
    * @param username
    * @param ipAddr 
    */
   protected void userConnection(String username, InetAddress ipAddr){
       type.setNull();
       if (listUsers.containsKey(username))        // Si on a deja qqn de ce username
            System.out.println("L'utilisateur "+username+" est déjà dans la liste");
        else {
            listUsers.put(username, ipAddr);
            listUsersInverse.put(ipAddr,username);
            this.type.setUserIN(username);
            //Indique que l'état du Model a changé, la méthode hasChanged retourne true now
            this.setChanged();
            notifyObservers(type);
            this.clearChanged();
            System.out.println("L'utilisateur "+username+" vient de se connecter");
            type.setNull();
        }
   }
   
   
     /**
    *  Méthode correspondant à la déconnexion d'un utilisateur du chat
    * Lors de la déconnexion d'un nouvel utilisateur, le Model change d'état
    * @param username 
    */
   
    protected void userDisconnection(String username){
        type.setNull();
        System.out.println("L'utilisateur "+username+" vient de se deconnecter");
        listUsers.remove(username);
        listUsersInverse.remove(getAddrFromLogin(username));
        type.setNull();
        //this.type.setUserIN(null);
        this.type.setUserOUT(username);
        this.setChanged();
        notifyObservers(type);
        this.clearChanged();
        System.out.println("L'utilisateur "+username+" vient de se deconnecter");
        type.setNull();
   }
   
      /**
     * Méthode correspondant à la réception d'un message de la part d'un utilisateur distant
     * Lors de la réception d'un message, le Model change d'état
     * @param username
     * @param text 
     */
   protected void userReception(String username, String text){
        type.setNull();
        System.out.println("L'utilisateur "+username+" vient d'envoyer le message suivant : "+text);
        this.type.setMessageIN(text);
        this.type.setLoginAssociated(username);
        this.setChanged();
        notifyObservers(type);
        this.clearChanged();
        type.setNull();
   }
   
     /**
    * Méthode correspondant au démarrage d'une conversation du localUser avec un autre utilisateur
    * Le Model change d'état
    * @param username 
    */
   protected void userConversation(String username){
       type.setNull();
       System.out.println("On commence une conversation avec "+username);
       this.type.setOpenWindow(username);
       this.setChanged();
       notifyObservers(type);
       this.clearChanged();
       type.setNull();
   }
   
   

   /**
    * Méthode permettant d'ajouter un Observer particulier : le ChatGUI
    *Le ChatGUI sera donc informé de chaque changement d'état du Model
    * @param gui 
    */
   
   public void addGui(ChatGUI gui){
       this.addObserver(gui);
   }
   
     /**
    *Méthode permettant d'ajouter un Observer particulier : le ChatNI
    *Le ChatNI sera donc informé de chaque changement d'état du Model
    * @param ni 
    */
    public void addNi(ChatNI ni){
       this.addObserver(ni);
   }
    
}
